#!coding:utf-8
import unittest
from cvirt.common import config, exception
import os

config.setup_logging()
from cvirt.manager.models import *
from cvirt.cnode.network import api
from mock import MagicMock
from cvirt.common.test import BaseTest

conf = config.load_settings()


class test_network_api(BaseTest):
    def setUp(self):
        self.datacenter = Datacenter.objects.create(name='dj')
        self.cluster = Cluster.objects.create(name='test-cluster', description='ccccc', cpufamily='AMD',datacenter=self.datacenter)
        self.net = Network.objects.create(name='test-nat', address='192.168.12.0', netmask='255.255.255.0',
                                          rundhcp=True, dhcp_start='192.168.12.100', dhcp_end="192.168.12.150",
                                          networktype=0, cluster=self.cluster, cidr='192.168.12.0/24')

        api.conn = MagicMock()
        api.conn.networkLookupByName = MagicMock(side_effect=Exception('Boom!'))
        api.conn.networkDefineXML.return_value = True

        #for bridge network
        # self.hostinterface = ServerInterface.objects.create(name='eth0', link_base=100, type=2, cluster=self.cluster)
        self.bnet = Network.objects.create(name='cvirt-bridge', networktype=2, cluster=self.cluster,
                                           # address="172.16.10.0",
                                           netmask="255.255.255.0", cidr='172.16.10.0/24', bridge='br0',
                                           rundhcp=True,
                                           dhcp_start='172.16.10.110',
                                           dhcp_end='172.16.10.250', gateway='172.16.10.1', dns1='221.228.255.1',
                                           dns2='8.8.8.8')


        #for allocate fixip
        self.host = Server.objects.create(host_name='testhost', ip='172.16.10.36', password='ssss', arch='x86',
                                          os='linux', hypervisor='kvm',
                                          cpu_type='amd', qemu_version='1.2', cluster=self.cluster)
        self.storage = Storage.objects.create(name='teststorage', type='nfs', mount_point='/opt', host='172.16.10.44',
                                              username='root', password='123',
                                              cluster=self.cluster)
        self.instance = Instance.objects.create(name='testvm', host=self.host, storage=self.storage, status='running',
                                                uuid='dasdsfsadhfaksf',
                                                vcpu=1, memory=1024, power_status=0)
        self.interface = Interface.objects.create(name='eth0', mac='40:16:9f:f2:16:d9', model='virtio',
                                                  network=self.bnet, instance=self.instance)

    def test_create_nat_with_wrong_params(self):
        self.net.networktype = 5
        self.assertRaises(exception.NetworkInitFailure, api.create_nat_network, self.net)


    def test_create_nat_network(self):

        net = api.create_nat_network(self.net)
        self.assertEqual(net, self.net)
        api.conn.networkLookupByName.assert_called_with('test-nat')
        api.conn.networkDefineXML.assert_called_with('<network>'
                                                     '<name>test-nat</name>'
                                                     '<bridge delay="0" stp="on"/>'
                                                     '<forward mode="nat"/>'
                                                     '<ip netmask="255.255.255.0" address="192.168.12.0">'
                                                     '<dhcp>'
                                                     '<range start="192.168.12.100" end="192.168.12.150"/>'
                                                     '</dhcp>'
                                                     '</ip>'
                                                     '</network>')

    def test_create_isolate_network(self):
        self.net.networktype = 1
        net = api.create_isolate_network(self.net)
        self.assertEqual(net, self.net)
        api.conn.networkLookupByName.assert_called_with('test-nat')
        api.conn.networkDefineXML.assert_called_with('<network>'
                                                     '<name>test-nat</name>'
                                                     '<bridge delay="0" stp="on"/>'
                                                     '<ip netmask="255.255.255.0" address="192.168.12.0">'
                                                     '<dhcp>'
                                                     '<range start="192.168.12.100" end="192.168.12.150"/>'
                                                     '</dhcp>'
                                                     '</ip>'
                                                     '</network>')


    def _create_bridge(self):
        net = api.create_bridge_network(self.bnet, '172.16.10.25')
        self.assertEqual(net, self.bnet)
        api.conn.networkDefineXML.assert_called_with('<network>'
                                                     '<name>cvirt-bridge</name>'
                                                     '<forward mode="bridge"/>'
                                                     '<bridge name="br0"/>'
                                                     '</network>')

    def test_create_bridge_network(self):

        self.fixip = FixedIp.objects.create(address='172.16.10.88', network=self.bnet)
        self._create_bridge()

    def test_no_more_fixed_ip_for_network(self):
        self.assertRaises(exception.FixedIpNoMoreForNetwork, self._create_bridge)

    def test_allocate_fixed_ip(self):
        self.fixip = FixedIp.objects.create(address='172.16.10.88', network=self.bnet)
        fixedip = api.allocate_fixed_ip(self.interface)
        i = Interface.objects.get(pk=self.interface.id)
        self.assertEqual(i.fixedip.allocated, True)
        self.assertEqual(fixedip.interface, i)
        self.assertEqual(i.fixedip.address, fixedip.address)

        self.assertEqual("40:16:9f:f2:16:d9,testvm,172.16.10.88",
                         file(os.path.abspath('%s/thor-%s.conf' % (conf['networks_path'], self.bnet.bridge))).read())

    def test_unallocate_fixed_ip(self):
        self.fixip = FixedIp.objects.create(address='172.16.10.88', network=self.bnet)
        self.fixip.allocated = True
        self.fixip.save()
        self.interface.fixedip = self.fixip
        self.interface.save()
        api.unallocate_fixed_ip(self.interface)

        i = Interface.objects.get(pk=self.interface.id)
        fi = FixedIp.objects.get(pk=self.fixip.id)
        self.assertEqual(fi.allocated, False)
        self.assertEqual(i.fixedip, None)
